/**
 * CountdownLatch类
 * 主要还是用于同步问题
 * 
 * @project_name thread
 * @package_name com.gxwz.thread
 * @file_name Java5SpecificCountdownLatchClass4Thread.java
 */
package com.gxwz.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * CountdownLatch 这个类在初始化的时候给他一个计数器，
 * 每次调用countDown方法计数器会减1，
 * 减到0的时候开始往下执行。用给定的计算器初始化CountdownLatch。
 * 由于调用了countDownLatch方法。所以在当前的计数器到达0之前await方法会一直受阻塞。
 * 之后，会释放所有等待的线程。await的所有回叙调用都将立即 返回。
 * 这种现象只出现一次----计数器无法被重置。如果要重置计数器就使用CyclicBarrier。
 * @author chendequan
 * @email 1527254027@qq.com
 * @datetime 2013-9-6 下午01:36:22
 * 
 */
public class Java5SpecificCountdownLatchClass4Thread {

	public static void main(String[] args) {
		// newCachedThreadPool 创建一个可根据需要创建新线程的线程池，但是在以前构造的线程可用时将重用它们。
		ExecutorService service = Executors.newCachedThreadPool();
		// 构造一个用给定计数初始化的 CountDownLatch。
		final CountDownLatch cdlOrder = new CountDownLatch(1);
		final CountDownLatch cdlAnswer = new CountDownLatch(3);

//		创建3个线程。。
		for (int i = 0; i < 3; i++) {
			Runnable runnable = new Runnable() {
				/*
				 * (non-Javadoc)
				 * 
				 * @see java.lang.Runnable#run()
				 */
				@Override
				public void run() {
					try {
						System.out.println("运动员： "
								+ Thread.currentThread().getName() + "准备完毕！！");
//						使当前线程在锁存器倒计数至零之前一直等待，除非线程被中断。
						cdlOrder.await();  //程序会在这里停住。直到被唤醒
						System.out
								.println("运动员： "
										+ Thread.currentThread().getName()
										+ "已经接受命令！！");
						
						Thread.sleep((long)(Math.random() * 5000));
						System.out.println("------------------");
						System.out.println("运动员： "
										+ Thread.currentThread().getName()
										+ "已经到达终点！！");
//						 递减锁存器的计数，如果计数到达零，则释放所有等待的线程。
//						没执行一次这个函数计数器减 1
						cdlAnswer.countDown();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
//			执行线程
			service.execute(runnable);
		}
		System.out.println("start main Thread。。。");
		try {
			Thread.sleep((long) (Math.random() * 5000));
			System.out.println("裁判" + Thread.currentThread().getName() 
					+ "即将打响信号枪！");
//			递减计数器，当计数为0是释放所有等待的线程
//			每執行一次次函數计数器都会减少一，直到为0
//			cdlOrder初始化计算器是 1
			cdlOrder.countDown();
			System.out.println("裁判" + Thread.currentThread().getName() 
					+ "已经打响信号枪，等待运动员赛跑结束！！");
//			使当前线程在计数器为0之前一直等待，除非程序被中断
			cdlAnswer.await();
			System.out.println("裁判" + Thread.currentThread().getName() 
					+ "已经得到赛跑结果！！");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		service.shutdown();
	}
}
